#include "stdafx.h"
#include "VertexBuffer.h"

namespace Cvekas {

VertexBuffer::VertexBuffer(ResourceId id, D3DDevicePtr device, const std::string& name,
		VertexFormat format, uint vertex_count, bool is_dynamic)
		:
GpuBuffer(id, device, name, is_dynamic),
format(format),
vertex_count(vertex_count)
{
	usage = is_dynamic ? D3DUSAGE_DYNAMIC : 0;
	size_in_bytes = format.getSize() * vertex_count;
	create();
}

VertexBuffer::~VertexBuffer()
{
	if(!is_released)
	{
		safeRelease(vertex_buffer);
		LOG(FORMAT("Vertex buffer %s released", % name));
	}
}

bool VertexBuffer::isLocked() const
{
	return is_locked;
}

LockedBuffer VertexBuffer::lock(bool read_only)
{
	if(is_locked)
		throw EXCEPTION("Vertex buffer is already locked!");

	is_locked = true;

	void* data;
	DWORD usage;

	if(is_dynamic)
		usage = D3DLOCK_DISCARD;
	else
		usage = read_only ? D3DLOCK_READONLY : 0;

	E_E(vertex_buffer->Lock(0, 0, &data, usage));

	LockedBuffer result;
	result.data = data;
	result.size = size_in_bytes;

	return result;
}

void VertexBuffer::unlock()
{
	if(!is_locked)
		throw EXCEPTION("Index buffer is not locked!");

	E_E(vertex_buffer->Unlock());
	is_locked = false;
}

uint VertexBuffer::getVertexCount() const
{
	return vertex_count;
}

VertexFormat& VertexBuffer::getVertexFormat()
{
	return format;
}

IDirect3DVertexBuffer9* VertexBuffer::getD3DVertexBuffer() const
{
	if(is_ready)
		return vertex_buffer;
	else
		throw EXCEPTION("Vertex buffer is not ready for usage");
}


void VertexBuffer::create()
{
	LOG(FORMAT("Creating vertex buffer %s", % name));

	DWORD fvf = 0; // Don't use FVF, IDirect3DVertexDeclaration9 is more flexible
	D3DPOOL pool = is_dynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
	
	device->CreateVertexBuffer(size_in_bytes, usage, fvf, pool, &vertex_buffer, NULL);
	
	is_ready = true;
	is_locked = false;
}

void VertexBuffer::onDeviceLost()
{
	// Only dynamic buffers must be released on device lost
	if(is_dynamic && !is_released)
	{
		LOG(FORMAT("Releasing dynamic vertex buffer %s", % name));
		safeRelease(vertex_buffer);
		is_released = true;
	}

	is_ready = false;
}

void VertexBuffer::onDeviceReset()
{
	if(is_dynamic && is_released)
	{
		create();
		is_released = false;
	}

	is_ready = true;
}

} // namespace
